﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using Enlightener.Engine.Structs__Enums___Interfaces;
using Enlightener.Engine.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;

namespace Enlightener.Engine.Deobfuscator.Tasks._1_7
{
    internal unsafe class AntiTamper : DeobfuscationTask
    {
        public AntiTamper(AssemblyDefinition asmDef)
            : base(asmDef)
        {
        }

        [DeobfuscationPhase(1, "Locate unpacking method")]
        public static bool Phase1()
        {
            var ctor =
                AsmDef.MainModule.Types.First(t => t.Name == "<Module>").Methods.FirstOrDefault(
                    m => m.IsConstructor && m.Body.Instructions.Count >= 1);

            if (ctor == null)
            {
                PhaseError = new PhaseError
                                 {
                                     Level = PhaseError.ErrorLevel.Minor,
                                     Message = "No anti-tamper?"
                                 };

                EmergencyCancel = true;
                return true;
            }

            var badInstr =
                ctor.Body.Instructions.FirstOrDefault(
                    i => i.OpCode == OpCodes.Call && IsUnpacker((i.Operand as MethodReference).Resolve()));

            if (badInstr == null)
            {
                PhaseError = new PhaseError
                                 {
                                     Level = PhaseError.ErrorLevel.Critical,
                                     Message = "Could not locate unpacker method!"
                                 };

                return false;
            }

            PhaseParam = (badInstr.Operand as MethodReference).Resolve();
            Logger.VSLog("Found unpacker method at " + PhaseParam.Name);

            return true;
        }

        private static bool IsUnpacker(MethodDefinition mDef)
        {
            if (!mDef.HasBody)
                return false;

            if (mDef.Body.Variables.Count != 43)
                return false;

            if (mDef.Parameters.Count != 0)
                return false;

            return true;
        }

    }
}
